package godau.fynn.bandcampdirect.activity.fragment;

import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.CookieManager;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import godau.fynn.bandcampdirect.R;
import godau.fynn.bandcampdirect.SharedPreferences;
import godau.fynn.bandcampdirect.activity.AlbumActivity;
import godau.fynn.bandcampdirect.bandcamp.Bandcamp;
import godau.fynn.bandcampdirect.bandcamp.Constants;
import godau.fynn.bandcampdirect.discover.Database;
import godau.fynn.bandcampdirect.model.Album;
import godau.fynn.bandcampdirect.model.User;
import org.json.JSONException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.util.ArrayList;

import static android.app.Activity.RESULT_OK;
import static godau.fynn.bandcampdirect.activity.DiscoverActivity.EXTRA_URL;
import static godau.fynn.bandcampdirect.bandcamp.Constants.DISCOVER_URL;

public class DiscoverFragment extends Fragment {

    private TextView status;
    private WebView webView;

    public static DiscoverFragment getInstance(String url) {
        Bundle bundle = new Bundle();
        bundle.putString(EXTRA_URL, url);
        DiscoverFragment fragment = new DiscoverFragment();
        fragment.setArguments(bundle);
        return fragment;
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.content_discover, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {

        status = view.findViewById(R.id.text);

        SharedPreferences sharedPreferences = new SharedPreferences(getContext());
        User user = new User(sharedPreferences.getString(SharedPreferences.IDENTITY_TOKEN, null));

        Bandcamp bandcamp = new Bandcamp(user);

        Database database = Database.build(getContext());

        webView = view.findViewById(R.id.webview);

        webView.getSettings().setJavaScriptEnabled(true);
        webView.setWebViewClient(new WebViewClient());

        String url;
        if (getArguments() != null) {
            url = getArguments().getString(EXTRA_URL);
        } else {
            url = DISCOVER_URL;
        }


        CookieManager cookieMan = CookieManager.getInstance();
        cookieMan.setCookie("bandcamp.com", user.getIdentityCookie(), value -> {
            webView.loadUrl(url);
        });


        view.findViewById(R.id.discover).setOnClickListener((clickedView) -> {

            view.findViewById(R.id.webview).setVisibility(View.INVISIBLE);
            view.findViewById(R.id.discover).setVisibility(View.GONE);

            TextView status = view.findViewById(R.id.text);

            status.setText("Counting");

            // Get current URL
            String cUrl = webView.getUrl();
            bandcamp.request(cUrl, new Handler((message) -> {
                String html = Bandcamp.getHtmlFromMessage(message);


                ArrayList<String> discoverUrls = new ArrayList<>();
                discoverUrls.add(cUrl);

                // Find urls
                Document d = Jsoup.parse(html);

                Elements as = d.getElementsByTag("a");

                as:
                for (Element a :
                        as) {
                    // Get discover URL
                    String dUrl = a.attr("href");

                    // Test against blacklist
                    blacklist:
                    for (String black :
                            Constants.DISCOVER_BLACKLIST) {
                        if (dUrl.contains(black)) {
                            continue as;
                        }
                    }

                    // https everywhere
                    dUrl = dUrl.replaceAll("http://", "https://");


                    if (!dUrl.contains("https://")) {
                        // Link not absolute

                        // What kind of relative is it?
                        if (dUrl.startsWith("/")) {
                            dUrl = "https://" + Uri.parse(cUrl).getHost() + dUrl;
                        } else {
                            dUrl = cUrl + dUrl;
                            dUrl = dUrl.replaceAll("//(?!.*bandcamp)", "/");
                        }
                    }

                    // Test for duplicate
                    if (discoverUrls.contains(dUrl)) {
                        continue as;
                    }

                    discoverUrls.add(dUrl);


                    Log.d("DISCOVERA", dUrl);
                }


                // Download each discoverUrl

                final int[] discoveredItems = {0};

                for (String discoverUrl :
                        discoverUrls) {
                    bandcamp.request(discoverUrl, new Handler((discoverMessage) -> {
                        String discoveredHtml = Bandcamp.getHtmlFromMessage(discoverMessage);
                        try {
                            Album album = new Album(discoveredHtml);


                            if (album.getTracks().size() > 1) {
                                AlbumActivity.discoverTracks(album, bandcamp, database, new Handler((msg -> {
                                    // Tracks will be written to database by function

                                    discoveredItems[0]++;
                                    updateStatus(discoveredItems[0], discoverUrls);

                                    return false;
                                })), new Handler(msg -> {
                                    // Fail
                                    discoveredItems[0]++;
                                    updateStatus(discoveredItems[0], discoverUrls);
                                    return false;
                                }));
                            } else {

                                database.writeAlbumTracksAsync(album);
                                discoveredItems[0]++;
                                updateStatus(discoveredItems[0], discoverUrls);

                            }




                        } catch (JSONException | ArrayIndexOutOfBoundsException e) {
                            // Apparently, this item can't be discovered, but let's not spam logcat
                            discoveredItems[0]++;
                            updateStatus(discoveredItems[0], discoverUrls);
                        }
                        return false;
                    }), new Handler((discoverMessage) -> {
                        discoveredItems[0]++;

                        updateStatus(discoveredItems[0], discoverUrls);


                        return false;
                    }));
                }


                return false;
            }), new Handler((message) -> {
                if (getContext() != null)
                    Toast.makeText(getContext(), "An error occured", Toast.LENGTH_SHORT).show();
                return false;
            }));

        });
    }

    private void updateStatus(int discovered, ArrayList<?> toDiscover) {

        if (discovered >= toDiscover.size()) {
            // This was the last item
            status.setText("Done");
            if (getActivity() != null) {
                getActivity().setResult(RESULT_OK);
                getActivity().finish();
            }
        } else {
            status.setText("Discovering " + (toDiscover.size() - discovered) + " items");
        }
    }

    /**
     * Delegate back presses to this fragment to navigate back in the web view.
     *
     * @return True if the press was consumed
     */
    public boolean onBackPressed() {
        if (webView.canGoBack()) {
            webView.goBack();
            return true;
        } else {
            return false;
        }
    }
}
